/**********************************************************************
 * FILE : JMSWorker.java
 * CREATE DATE : 2011-11-24
 * DESCRIPTION :
 * CHANGE HISTORY LOG
 * ---------------------------------------------------------------------
 * NO.| DATE | NAME | REASON | DESCRIPTION
 * ---------------------------------------------------------------------
 * 1 | 2011-11-24 | Sting | 创建草稿版本
 * ---------------------------------------------------------------------
 */
package com.sgm.de.benchmark;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.BindException;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.fastjson.JSON;
import com.sgm.de.benchmark.act.IAct;

/**
 * @author Sting
 *         <p>
 */
public class JMSProcesser {

    private static final Logger logger = LoggerFactory.getLogger(JMSProcesser.class);
    public static volatile boolean isRunning = false;
    public static int listenerPort = 8889;
    public static BKCode testType = null;
    public int messageLimit;
    public int timeSecLimit;

    ProcessContext ctx;


    public static void main(String[] args) throws Exception {
        logger.info("[processor]starting............");
        JMSProcesser worker = new JMSProcesser(true);
        if (args.length > 0) {
            int agentPort = Integer.parseInt(args[0]);
            logger.info("get agent port,try to connect.....");
            responseAgent(agentPort);
        }
    }

    /**
     * 回复给建立进程
     * 
     * @param agentPort
     */
    private static void responseAgent(int agentPort) {
        Socket s = null;
        int count = 10;
        while (s == null && count-- > 0) {
            try {
                s = new Socket("127.0.0.1", agentPort);
            } catch (UnknownHostException e) {
            } catch (IOException e) {
            } finally {

                if (s == null)
                    logger.info("connect failed!");
                    try {
                        Thread.sleep(500);
                    } catch (InterruptedException e) {
                        continue;
                    }
            }
        }
        if (s != null) {
            logger.info("manage agent connected");
            PrintWriter bw;
            try {
                bw = new PrintWriter(s.getOutputStream());
                bw.write(s.getInetAddress().getHostAddress() + ":" + listenerPort);
                bw.flush();
                s.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * @param autoListener 是否自动开始启动监听线程
     */
    public JMSProcesser(boolean autoListener) {
        isRunning = true;
        ctx = new ProcessContext();
        ctx.processor = this;
        if (autoListener) {
            try {
                startListen();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 启动监听线程,监听调用
     * 
     * @throws Exception
     */
    public void startListen() throws Exception {
        new Thread(new Runnable() {
            ServerSocket server = null;
            Socket client = null;
            BufferedReader request = null;
            PrintWriter response = null;
            @Override
            public void run() {

                while (isRunning) {
                    server = createServer();
                    try {
                        client = server.accept();
                        logger.info("[processor]socket get incomming connection!");
                        request = new BufferedReader(new InputStreamReader(client.getInputStream()));
                        response = new PrintWriter(client.getOutputStream(), true);
                        response.write("ack");
                        ctx.response = response;
                        ctx.fromAgent = request;

                        while (isRunning && request != null) {
                            String line = request.readLine();
                            Cmd cmd = JSON.parseObject(line, Cmd.class);
                            IAct actor = cmd.guessAct();
                            actor.exec(ctx);
                        }
                    } catch (Exception e1) {
                        e1.printStackTrace();
                        destroyListener();
                        continue;
                    }
                }
                logger.info("stop running");
                destroyListener();
            }

            private void destroyListener() {
                try {
                    if (request != null)
                        request.close();
                    if (response != null)
                        response.close();
                    if (client != null)
                        client.close();
                    if (server != null)
                        server.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }

            }

            public ServerSocket createServer() {
                ServerSocket server = null;
                try {
                    server = new ServerSocket(listenerPort);
                } catch (BindException b) {
                    logger.info("socket port " + listenerPort + " is in use,change to " + ++listenerPort);
                    return createServer();
                } catch (IOException e) {
                    e.printStackTrace();
                    logger.info("socket port " + listenerPort + " is ioException,rebind to " + ++listenerPort);
                    return createServer();
                }
                logger.info("[processor] process listener bind at " + listenerPort);
                return server;
            }
        }).start();
    }

    public void commandLocal(String line) {
        Cmd cmd = JSON.parseObject(line, Cmd.class);
        IAct actor = cmd.guessAct();
        try {
            actor.exec(ctx);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void distory() {
        isRunning = false;
    }


}
